home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1993 / Internet Info CD-ROM (Walnut Creek) (1993).iso / networking / ip / ka9q / osrc.arc / MAIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-05  |  16.8 KB  |  867 lines

  1. /* Main network program - provides both client and server functions */
  2. #define HOSTNAMELEN 32        /* changed from 16 by Bdale 860812 */
  3. #include <stdio.h>
  4. #include <time.h>
  5. #if    defined(__STDC__) || defined(__TURBOC__)
  6. #include <stdarg.h>
  7. #endif
  8. #include "config.h"
  9. #include "global.h"
  10. #include "mbuf.h"
  11. #include "socket.h"
  12. #include "iface.h"
  13. #include "ftpcli.h"
  14. #include "telnet.h"
  15. #include "ax25tnc.h"
  16. #include "remote.h"
  17. #include "session.h"
  18. #include "cmdparse.h"
  19. #include "ax25.h"
  20. #include "enet.h"
  21. #include "timer.h"
  22. #include "proc.h"
  23. #include "tty.h"
  24. #include "daemon.h"
  25. #include "usock.h"
  26.  
  27. #ifdef    ASY
  28. #include "asy.h"
  29. #include "slip.h"
  30. #endif
  31.  
  32. #ifdef    NRS
  33. #include "nrs.h"
  34. #endif
  35.  
  36. #ifdef UNIX        /* BSD or SYS5 */
  37. #include "unix.h"
  38. #endif
  39.  
  40. #ifdef AMIGA
  41. #include "amiga.h"
  42. #endif
  43.  
  44. #ifdef MAC
  45. #include "mac.h"
  46. #endif
  47.  
  48. #ifdef MSDOS
  49. #include "asy.h"
  50. #endif
  51.  
  52. #ifdef    TRACE
  53. #include "trace.h"
  54. /* Dummy structure for loopback tracing */
  55. struct iface Loopback = { NULLIF, "loopback" };
  56. #endif
  57.  
  58. extern struct cmds Cmds[],Startcmds[],Stopcmds[];
  59. extern struct daemon Daemons[];
  60. extern struct iface *Ifaces;
  61. extern char Version[];
  62. extern char *Startup;    /* File to read startup commands from */
  63. extern int Refuse_echo;
  64. extern int Unix_line_mode;
  65. extern struct cmds Attab[];
  66. extern struct iface *Ifaces;
  67. extern char *Socktypes[];
  68. extern char *Rempass;
  69. void showtrace();
  70.  
  71. int32 Heapsize = HEAPSIZE * (long)1024;
  72. unsigned Nsessions = NSESSIONS;
  73. #ifndef    MSDOS            /* PC uses F-10 key always */
  74. static char Escape = 0x1d;    /* default escape character is ^] */
  75. #endif
  76.  
  77. char Badhost[] = "Unknown host %s\n";
  78. char Hostname[HOSTNAMELEN];    
  79. int16 Lport = 1024;
  80. char Prompt[] = "net> ";
  81. char Nospace[] = "No space!!\n";    /* Generic malloc fail message */
  82. struct mbuf *Hopper;
  83. FILE *Logfp;
  84. struct mbuf *Cmdq;
  85. struct proc *Cmdpp;
  86.  
  87. main(argc,argv)
  88. int argc;
  89. char *argv[];
  90. {
  91.     char *inbuf,*intmp;
  92.     FILE *fp;
  93.     struct daemon *tp;
  94.     struct mbuf *bp;
  95.     int c;
  96.     extern char *optarg;
  97.     extern int optind;
  98.  
  99.     while((c = getopt(argc,argv,"s:d:m:")) != EOF){
  100.         switch(c){
  101.         case 's':    /* Number of sockets */
  102.             Nusock = atoi(optarg);
  103.             break;
  104.         case 'd':    /* Root directory for various files */
  105.             initroot(optarg);
  106.             break;
  107.         case 'm':    /* Heap memory size */
  108.             Heapsize = 1024 * atol(optarg);
  109.             break;
  110.         }
  111.     }
  112.     kinit();
  113.     ioinit(Heapsize);
  114.     sockinit();
  115.     Cmdpp = mainproc("cmdintrp");
  116.     ttysetmode(TTY_ECHO|TTY_EDIT);
  117.     printf("KA9Q Internet Protocol Package, v%s\n",Version);
  118.     printf("Copyright 1989 by Phil Karn, KA9Q\n");
  119.     fflush(stdout);
  120.     Sessions = (struct session *)calloc(Nsessions,sizeof(struct session));
  121.  
  122.     if(optind < argc){
  123.         /* Read startup file named on command line */
  124.         if((fp = fopen(argv[optind],READ_TEXT)) == NULLFILE)
  125.             printf("Can't read config file %s: %s\n",
  126.              argv[optind],sys_errlist[errno]);
  127.     } else {
  128.         fp = fopen(Startup,READ_TEXT);
  129.     }
  130.     if(fp != NULLFILE){
  131.         inbuf = malloc(BUFSIZ);
  132.         intmp = malloc(BUFSIZ);
  133.         while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
  134.             strcpy(intmp,inbuf);
  135.             if(cmdparse(Cmds,inbuf,NULL) != 0){
  136.                 printf("input line: %s",intmp);
  137.             }
  138.         }
  139.         fclose(fp);
  140.         free(inbuf);
  141.         free(intmp);
  142.     }
  143.     /* Start background Daemons */
  144.     for(tp=Daemons;;tp++){
  145.         if(tp->name == NULLCHAR)
  146.             break;
  147.         newproc(tp->name,tp->stksize,tp->fp,0,NULLCHAR,NULL);
  148.     }
  149.     /* Now loop forever, processing commands */
  150.     for(;;){
  151.         printf(Prompt);
  152.         while(Cmdq == NULLBUF)
  153.             pwait(&Cmdq);
  154.         bp = dequeue(&Cmdq);
  155.         (void)cmdparse(Cmds,bp->data,Current);
  156.         free_p(bp);
  157.         ttysetmode(TTY_ECHO|TTY_EDIT);
  158.     }
  159. }
  160. /* Keyboard input process */
  161. void
  162. keyboard()
  163. {
  164.     int c;
  165.     struct mbuf *bp;
  166.  
  167.     /* Keyboard process loop */
  168.     for(;;){
  169.         c = kbread();
  170. #ifndef    MSDOS
  171.         if(c == Escape && Escape != 0)
  172.             c = -2;
  173. #endif
  174.         /* c == -2 means the command escape key */
  175.         if(c == -2){
  176.             /* Save current tty mode and set cooked */
  177.             if(Current != NULLSESSION){
  178.                 Current->ttymode = ttygetmode();
  179.                 Mode = CMD_MODE;
  180.                 ttysetmode(TTY_ECHO|TTY_EDIT);
  181.                 printf("\n");
  182.                 /* Wake up the command interpreter */
  183.                 alert(Cmdpp,0);
  184.             }
  185.         /* Else give to line editor; if done, queue it */
  186.         } else if((bp = ttydriv(c)) != NULLBUF){
  187.             switch(Mode){
  188.             case CMD_MODE:
  189.                 enqueue(&Cmdq,bp);
  190.                 break;
  191.             case CONV_MODE:
  192.                 enqueue(&Current->input,bp);
  193.                 break;
  194.             }
  195.         }
  196.     }
  197. }
  198. /* Process packets in the Hopper */
  199. void
  200. network()
  201. {
  202.     struct mbuf *bp;
  203.     struct phdr phdr;
  204.     char i_state;
  205.  
  206. loop:    i_state = dirps();
  207.     while(Hopper == NULLBUF)
  208.         pwait(&Hopper);
  209.     restore(i_state);
  210.  
  211.     /* Process the input packet */
  212.     bp = dequeue(&Hopper);
  213.     pullup(&bp,(char *)&phdr,sizeof(phdr));
  214.     dump(phdr.iface,IF_TRACE_IN,phdr.type,bp);
  215.     switch(phdr.type){
  216. #ifdef    AX25
  217.     case TYPE_KISS:
  218.         /* Toss the type field and handle as AX.25 */
  219.         pullup(&bp,NULLCHAR,1);    /*note fall-thru */
  220.     case TYPE_AX25:
  221.         ax_recv(phdr.iface,bp);
  222.         break;
  223. #endif
  224.     case TYPE_ETHER:
  225.         eproc(phdr.iface,bp);
  226.         break;
  227.     case TYPE_IP:
  228.         ip_route(bp,0);
  229.         break;
  230.     case TYPE_APPLETALK:
  231.     default:
  232.         free_p(bp);
  233.         break;
  234.     }
  235.     goto loop;
  236. }
  237. /* Standard commands called from main */
  238. int
  239. dodelete(argc,argv)
  240. int argc;
  241. char *argv[];
  242. {
  243.     int i;
  244.  
  245.     for(i=1;i < argc; i++){
  246.         if(unlink(argv[i]) == -1){
  247.             printf("Can't delete %s: %s\n",
  248.              argv[i],sys_errlist[errno]);
  249.         }
  250.     }
  251.     return 0;
  252. }
  253. int
  254. dorename(argc,argv)
  255. int argc;
  256. char *argv[];
  257. {
  258.     if(rename(argv[1],argv[2]) == -1)
  259.         printf("Can't rename: %s\n",sys_errlist[errno]);
  260.     return 0;
  261. }
  262. int
  263. doexit(argc,argv)
  264. int argc;
  265. char *argv[];
  266. {
  267.     reset_all();
  268.     iostop();
  269.     exit(0);
  270. }
  271. int
  272. dohostname(argc,argv)
  273. int argc;
  274. char *argv[];
  275. {
  276.     if(argc < 2)
  277.         printf("%s\n",Hostname);
  278.     else 
  279.         strncpy(Hostname,argv[1],HOSTNAMELEN);
  280.     return 0;
  281. }
  282. int
  283. dolog(argc,argv)
  284. int argc;
  285. char *argv[];
  286. {
  287.     static char logname[15];
  288.  
  289.     if(argc < 2){
  290.         if(Logfp)
  291.             printf("Logging to %s\n",logname);
  292.         else
  293.             printf("Logging off\n");
  294.         return 0;
  295.     }
  296.     if(Logfp){
  297.         fclose(Logfp);
  298.         Logfp = NULLFILE;
  299.     }
  300.     if(strcmp(argv[1],"stop") != 0){
  301.         strncpy(logname,argv[1],15);
  302.         Logfp = fopen(logname,APPEND_TEXT);
  303.     }
  304.     return 0;
  305. }
  306. int
  307. dohelp(argc,argv)
  308. int argc;
  309. char *argv[];
  310. {
  311.     register struct cmds *cmdp;
  312.     int i,j;
  313.  
  314.     printf("Main commands:\n");
  315.     for(i=0,cmdp = Cmds;cmdp->name != NULL;cmdp++,i++){
  316.         printf("%s",cmdp->name);
  317.         if((i % 4) == 3)
  318.             printf("\n");
  319.         else {
  320.             for(j=strlen(cmdp->name);j < 16; j++)
  321.                 putchar(' ');
  322.         }
  323.     }
  324.     if((i % 4) != 0)
  325.         printf("\n");
  326.     return 0;
  327. }
  328. int
  329. doecho(argc,argv)
  330. int argc;
  331. char *argv[];
  332. {
  333.     if(argc < 2){
  334.         if(Refuse_echo)
  335.             printf("Refuse\n");
  336.         else
  337.             printf("Accept\n");
  338.     } else {
  339.         if(argv[1][0] == 'r')
  340.             Refuse_echo = 1;
  341.         else if(argv[1][0] == 'a')
  342.             Refuse_echo = 0;
  343.         else
  344.             return -1;
  345.     }
  346.     return 0;
  347. }
  348. /* set for unix end of line for remote echo mode telnet */
  349. int
  350. doeol(argc,argv)
  351. int argc;
  352. char *argv[];
  353. {
  354.     if(argc < 2){
  355.         if(Unix_line_mode)
  356.             printf("Unix\n");
  357.         else
  358.             printf("Standard\n");
  359.     } else {
  360.         if(strcmp(argv[1],"unix") == 0)
  361.             Unix_line_mode = 1;
  362.         else if(strcmp(argv[1],"standard") == 0)
  363.             Unix_line_mode = 0;
  364.         else {
  365.             return -1;
  366.         }
  367.     }
  368.     return 0;
  369. }
  370. /* Attach an interface
  371.  * Syntax: attach <hw type> <I/O address> <vector> <mode> <label> <bufsize> [<speed>]
  372.  */
  373. int
  374. doattach(argc,argv,envp)
  375. int argc;
  376. char *argv[];
  377. void *envp;
  378. {
  379.     return subcmd(Attab,argc,argv,envp);
  380. }
  381. /* Manipulate I/O device parameters */
  382. int
  383. doparam(argc,argv)
  384. int argc;
  385. char *argv[];
  386. {
  387.     register struct iface *ifp;
  388.  
  389.     for(ifp=Ifaces;ifp != NULLIF;ifp = ifp->next){
  390.         if(strcmp(argv[1],ifp->name) == 0)
  391.             break;
  392.     }
  393.     if(ifp == NULLIF){
  394.         printf("Interface \"%s\" unknown\n",argv[1]);
  395.         return 1;
  396.     }
  397.     if(ifp->ioctl == NULLFP){
  398.         printf("Not supported\n");
  399.         return 1;
  400.     }
  401.     /* Pass rest of args to device-specific code */
  402.     return (*ifp->ioctl)(ifp,argc-2,argv+2);
  403. }
  404. /* Log messages of the form
  405.  * Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
  406.  */
  407. #if    defined(__STDC__) || defined(__TURBOC__)
  408. log(int s,char *fmt, ...)
  409. {
  410.     va_list ap;
  411.     char *cp;
  412.     long t;
  413.     int fd,i;
  414.     struct sockaddr fsocket;
  415.  
  416.     if(Logfp == NULLFILE)
  417.         return;
  418.  
  419.     time(&t);
  420.     cp = ctime(&t);
  421.     rip(cp);
  422.     i = SOCKSIZE;
  423.     fprintf(Logfp,"%s",cp);
  424.     if(getpeername(s,(char *)&fsocket,&i) != -1)
  425.         fprintf(Logfp," %s",psocket(&fsocket));
  426.  
  427.     fprintf(Logfp," - ");
  428.     va_start(ap,fmt);
  429.     vfprintf(Logfp,fmt,ap);
  430.     va_end(ap);
  431.     fprintf(Logfp,"\n");
  432.     fflush(Logfp);
  433. #ifdef    MSDOS
  434.     /* MS-DOS doesn't really flush files until they're closed */
  435.     fd = fileno(Logfp);
  436.     if((fd = dup(fd)) != -1)
  437.         close(fd);
  438. #endif
  439.  
  440. }
  441. #else
  442. /*VARARGS2*/
  443. log(s,fmt,arg1,arg2,arg3,arg4,arg5)
  444. int s;
  445. char *fmt;
  446. int arg1,arg2,arg3,arg4,arg5;
  447. {
  448.     char *cp;
  449.     long t;
  450.     int fd,i;
  451.     struct sockaddr fsocket;
  452.  
  453.     if(Logfp == NULLFILE)
  454.         return;
  455.     time(&t);
  456.     cp = ctime(&t);
  457.     rip(cp);
  458.     i = SOCKSIZE;
  459.     fprintf(Logfp,"%s",cp);
  460.     if(getpeername(s,(char *)&fsocket,&i) != -1)
  461.         fprintf(Logfp," %s",psocket(&fsocket));
  462.  
  463.     fprintf(Logfp," - ");
  464.     fprintf(Logfp,fmt,arg1,arg2,arg3,arg4,arg5);
  465.     fprintf(Logfp,"\n");
  466.     fflush(Logfp);
  467. #ifdef    MSDOS
  468.     /* MS-DOS doesn't really flush files until they're closed */
  469.     fd = fileno(Logfp);
  470.     if((fd = dup(fd)) != -1)
  471.         close(fd);
  472. #endif
  473. }
  474. #endif
  475. /* Configuration-dependent code */
  476.  
  477. /* List of supported hardware devices */
  478. int ec_attach(),asy_attach(),pc_attach(),eg_attach(),hapn_attach(),at_attach(),
  479.     nr_attach(),pk_attach(),hs_attach();
  480.  
  481. struct cmds Attab[] = {
  482. #ifdef    PC_EC
  483.     /* 3-Com Ethernet interface */
  484.     "3c500", ec_attach, 0, 7, 
  485.     "attach 3c500 <address> <vector> arpa <label> <buffers> <mtu>",
  486. #endif
  487. #ifdef    ASY
  488.     /* Ordinary PC asynchronous adaptor */
  489.     "asy", asy_attach, 0, 8, 
  490.     "attach asy <address> <vector> slip|ax25|nrs <label> <buffers> <mtu> <speed>",
  491. #endif
  492. #ifdef    PC100
  493.     /* PACCOMM PC-100 8530 HDLC adaptor */
  494.     "pc100", pc_attach, 0, 8, 
  495.     "attach pc100 <address> <vector> ax25 <label> <buffers> <mtu> <speed>",
  496. #endif
  497. #ifdef    EAGLE
  498.     /* EAGLE RS-232C 8530 HDLC adaptor */
  499.     "eagle", eg_attach, 0, 8,
  500.     "attach eagle <address> <vector> ax25 <label> <buffers> <mtu> <speed>",
  501. #endif
  502. #ifdef    HAPN
  503.     /* Hamilton Area Packet Radio (HAPN) 8273 HDLC adaptor */
  504.     "hapn", hapn_attach, 0, 8,
  505.     "attach hapn <address> <vector> ax25 <label> <rx bufsize> <mtu> csma|full",
  506. #endif
  507. #ifdef    APPLETALK
  508.     /* Macintosh AppleTalk */
  509.     "0", at_attach, 0, 7,
  510.     "attach 0 <protocol type> <device> arpa <label> <rx bufsize> <mtu>",
  511. #endif
  512. #ifdef NETROM
  513.     /* fake netrom interface */
  514.     "netrom", nr_attach, 0, 1,
  515.     "attach netrom",
  516. #endif
  517. #ifdef    PACKET
  518.     /* FTP Software's packet driver spec */
  519.     "packet", pk_attach, 0, 4,
  520.     "attach packet <int#> <label> <buffers> <mtu>",
  521. #endif
  522. #ifdef    HS
  523.     /* Special high speed driver for DRSI PCPA or Eagle cards */
  524.     "hs", hs_attach, 0, 7,
  525.     "attach hs <address> <vector> ax25 <label> <buffers> <mtu> <txdelay> <persistence>",
  526. #endif
  527.     NULLCHAR, NULLFP, 0, 0,
  528.     "Unknown device",
  529. };
  530.  
  531. /* Protocol tracing function pointers */
  532. #ifdef    TRACE
  533. int ax25_dump(),ether_dump(),ip_dump(),at_dump(),ki_dump();
  534.  
  535. int (*Tracef[])() = {
  536. #ifdef    AX25
  537.     ax25_dump,
  538. #else
  539.     NULLFP,
  540. #endif
  541.  
  542. #ifdef    ETHER
  543.     ether_dump,
  544. #else
  545.     NULLFP,
  546. #endif
  547.     ip_dump,
  548.  
  549. #ifdef    APPLETALK
  550.     at_dump,
  551. #else
  552.     NULLFP,
  553. #endif
  554.  
  555. #ifdef    KISS
  556.     ki_dump,
  557. #else
  558.     NULLFP,
  559. #endif
  560. };
  561. #else    /* TRACE */
  562. int (*Tracef[])() = { NULLFP };    /* No tracing at all */
  563. dump(iface,direction,type,bp)
  564. struct iface *iface;
  565. int direction;
  566. unsigned type;
  567. struct mbuf *bp;
  568. {
  569. }
  570. #endif    /* TRACE */
  571.  
  572. #ifndef    NETROM
  573. #ifdef    AX25
  574. struct ax25_addr Nr_nodebc;
  575. #endif    /* AX25 */
  576. nr_route(bp)
  577. struct mbuf *bp;
  578. {
  579.     free_p(bp);
  580. }
  581. nr_nodercv(bp)
  582. struct mbuf *bp;
  583. {
  584.     free_p(bp);
  585. }
  586. #endif    /* NETROM */
  587.  
  588. /* Display or set IP interface control flags */
  589. domode(argc,argv)
  590. int argc;
  591. char *argv[];
  592. {
  593.     register struct iface *ifp;
  594.  
  595.     for(ifp=Ifaces;ifp != NULLIF;ifp = ifp->next){
  596.         if(strcmp(argv[1],ifp->name) == 0)
  597.             break;
  598.     }
  599.     if(ifp == NULLIF){
  600.         printf("Interface \"%s\" unknown\n",argv[1]);
  601.         return 1;
  602.     }
  603.     if(argc < 3){
  604.         printf("%s: %s\n",ifp->name,
  605.          (ifp->flags & CONNECT_MODE) ? "VC mode" : "Datagram mode");
  606.         return 0;
  607.     }
  608.     switch(argv[2][0]){
  609.     case 'v':
  610.     case 'c':
  611.     case 'V':
  612.     case 'C':
  613.         ifp->flags = CONNECT_MODE;
  614.         break;
  615.     case 'd':
  616.     case 'D':
  617.         ifp->flags = DATAGRAM_MODE;
  618.         break;
  619.     default:
  620.         printf("Usage: %s [vc | datagram]\n",argv[0]);
  621.         return 1;
  622.     }
  623.     return 0;
  624. }
  625.  
  626. #ifdef SERVERS
  627. dostart(argc,argv,envp)
  628. int argc;
  629. char *argv[];
  630. void *envp;
  631. {
  632.     return subcmd(Startcmds,argc,argv,envp);
  633. }
  634. dostop(argc,argv,envp)
  635. int argc;
  636. char *argv[];
  637. void *envp;
  638. {
  639.     return subcmd(Stopcmds,argc,argv,envp);
  640. }
  641. #endif SERVERS
  642.  
  643. #ifdef    TRACE
  644. int
  645. dotrace(argc,argv)
  646. int argc;
  647. char *argv[];
  648. {
  649.     struct iface *ifp;
  650.  
  651.     if(argc < 2){
  652.         showtrace(&Loopback);
  653.         for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  654.             showtrace(ifp);
  655.         return 0;
  656.     }
  657.     if(strcmp("loopback",argv[1]) == 0)
  658.         ifp = &Loopback;
  659.     else 
  660.         for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  661.             if(strcmp(ifp->name,argv[1]) == 0)
  662.                 break;
  663.  
  664.     if(ifp == NULLIF){
  665.         printf("Interface %s unknown\n",argv[1]);
  666.         return 1;
  667.     }
  668.     if(argc >= 3)
  669.         ifp->trace = htoi(argv[2]);
  670.  
  671.     showtrace(ifp);
  672.     return 0;
  673. }
  674. /* Display the trace flags for a particular interface */
  675. void
  676. showtrace(ifp)
  677. register struct iface *ifp;
  678. {
  679.     if(ifp == NULLIF)
  680.         return;
  681.     printf("%s:",ifp->name);
  682.     if(ifp->trace & (IF_TRACE_IN | IF_TRACE_OUT)){
  683.         if(ifp->trace & IF_TRACE_IN)
  684.             printf(" input");
  685.         if(ifp->trace & IF_TRACE_OUT)
  686.             printf(" output");
  687.  
  688.         if(ifp->trace & IF_TRACE_HEX)
  689.             printf(" (Hex/ASCII dump)");
  690.         else if(ifp->trace & IF_TRACE_ASCII)
  691.             printf(" (ASCII dump)");
  692.         else
  693.             printf(" (headers only)");
  694.         printf("\n");
  695.     } else
  696.         printf(" tracing off\n");
  697. }
  698. #endif    /* TRACE */
  699.  
  700. #ifndef    MSDOS
  701. static
  702. int
  703. doescape(argc,argv)
  704. int argc;
  705. char *argv[];
  706. {
  707.     if(argc < 2)
  708.         printf("0x%x\n",Escape);
  709.     else 
  710.         Escape = *argv[1];
  711.     return 0;
  712. }
  713. #endif    MSDOS
  714. /* Generate system command packet. Synopsis:
  715.  * remote [-p port#] [-k key] [-a hostname] <hostname> reset|exit|kickme
  716.  */
  717. int
  718. doremote(argc,argv)
  719. int argc;
  720. char *argv[];
  721. {
  722.     struct sockaddr_in fsock;
  723.     int s,c;
  724.     char *data,x;
  725.     extern int errno;
  726.     extern char *optarg;
  727.     extern int optind;
  728.     int16 port,len;
  729.     char *key = NULLCHAR;
  730.     int klen;
  731.     int32 addr = 0;
  732.     char *cmd,*host;
  733.  
  734.     port = IPPORT_REMOTE;    /* Set default */
  735.     optind = 1;        /* reinit getopt() */
  736.     while((c = getopt(argc,argv,"a:p:k:s:")) != EOF){
  737.         switch(c){
  738.         case 'a':
  739.             addr = resolve(optarg);
  740.             break;
  741.         case 'p':
  742.             port = atoi(optarg);
  743.             break;
  744.         case 'k':
  745.             key = optarg;
  746.             klen = strlen(key);
  747.             break;
  748.         case 's':
  749.             Rempass = strdup(optarg);
  750.             return 0;    /* Only set local password */
  751.         }
  752.     }
  753.     if(optind > argc - 2){
  754.         printf("Insufficient args\n");
  755.         return -1;
  756.     }
  757.     host = argv[optind++];
  758.     cmd = argv[optind];
  759.     if((s = socket(AF_INET,SOCK_DGRAM,0)) == -1){
  760.         printf("socket failed\n");
  761.         return 1;
  762.     }
  763.     len = 1;
  764.     /* Did the user include a password or kickme target? */
  765.     if(addr != 0)
  766.         len += sizeof(int32);
  767.  
  768.     if(key != NULLCHAR)
  769.         len += klen;
  770.  
  771.     if(len == 1)
  772.         data = &x;
  773.     else
  774.         data = malloc(len);
  775.  
  776.     fsock.sin_family = AF_INET;
  777.     fsock.sin_addr.s_addr = resolve(host);
  778.     fsock.sin_port = port;
  779.  
  780.     switch(cmd[0]){
  781.     case 'r':
  782.         data[0] = SYS_RESET;
  783.         if(key != NULLCHAR)
  784.             strncpy(&data[1],key,klen);
  785.         break;
  786.     case 'e':
  787.         data[0] = SYS_EXIT;
  788.         if(key != NULLCHAR)
  789.             strncpy(&data[1],key,klen);
  790.         break;
  791.     case 'k':
  792.         data[0] = KICK_ME;
  793.         if(addr != 0)
  794.             put32(&data[1],addr);
  795.         break;
  796.     default:
  797.         printf("Unknown command %s\n",cmd);
  798.         goto cleanup;
  799.     }
  800.     /* Form the command packet and send it */
  801.     if(sendto(s,data,len,0,(char *)&fsock,sizeof(fsock)) == -1){
  802.         printf("sendto failed: %s\n",sys_errlist[errno]);
  803.         goto cleanup;
  804.     }
  805. cleanup:
  806.     if(data != &x)
  807.         free(data);
  808.     close_s(s);
  809.     return 0;
  810. }
  811.  
  812. /* Socket status display command */
  813. int
  814. dosock(argc,argv)
  815. int argc;
  816. char *argv[];
  817. {
  818.     register struct usock *up;
  819.     int s;
  820.  
  821.     if(argc < 2){
  822.         printf("S# Type    PCB      Owner\n");
  823.         for(s=0;s<Nusock;s++){
  824.             up = &Usock[s];
  825.             if(up->type == NOTUSED)
  826.                 continue;
  827.             printf("%2d %-8s%-8lx %lx (%s)\n",
  828.              s,Socktypes[up->type],ptol(up->cb.p),
  829.              ptol(up->owner),up->owner->name);
  830.         }
  831.         return 0;
  832.     }
  833.     s = atoi(argv[1]);
  834.     if(s < 0 || s >= Nusock){
  835.         printf("Number out of range\n");
  836.         return 1;
  837.     }
  838.     up = &Usock[s];
  839.     switch(up->type){
  840.     case NOTUSED:
  841.         printf("Not in use\n");
  842.         break;
  843.     case TYPE_TCP:
  844.         printf("TCP %lx\n",ptol(up->cb.tcb));
  845.         if(up->cb.p != NULL)
  846.             st_tcp(up->cb.tcb);
  847.         break;
  848.     case TYPE_UDP:
  849.         printf("UDP %lx\n",ptol(up->cb.udp));
  850.         if(up->cb.p != NULL)
  851.             st_udp(up->cb.udp,0);
  852.         break;
  853. #ifdef    AX25
  854.     case TYPE_AX25I:
  855.         printf("AX25I %lx\n",ptol(up->cb.ax25));
  856.         if(up->cb.p != NULL)
  857.             st_ax25(up->cb.ax25);
  858.         break;
  859.     case TYPE_AX25UI:
  860.         printf("AX25 UI\n");
  861.         break;
  862. #endif
  863.     }
  864.     return 0;    
  865. }
  866.  
  867.